﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Text.RegularExpressions;
using System.ServiceProcess;
using System.Threading.Tasks;

namespace PSBUtil {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {

        private string _currentName;
        public MainWindow() {
            InitializeComponent();
            Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;
        }

        private void applySetting_Click(object sender, RoutedEventArgs e) {
            var shouldWipe = wipeData.IsChecked ?? false;

            if (backplanes.SelectedIndex < 0) {
                MessageBox.Show("Please select backplane");
                return;
            }

            var selectedName = ((backplanes.SelectedItem as ComboBoxItem).Content as string).ToLower();

            foreach (var file in Directory.GetFiles(Environment.CurrentDirectory, "*.config", SearchOption.AllDirectories)) {
                var xml = File.ReadAllText(file);
                xml = xml.Replace(String.Format("app.{0}.xml", _currentName), String.Format("app.{0}.xml", selectedName));
                File.WriteAllText(file, xml);
            }

            foreach (var file in Directory.GetFiles(Environment.CurrentDirectory, "*configurations.xml", SearchOption.AllDirectories)) {
                var xml = File.ReadAllText(file);
                xml = xml.Replace(String.Format("configurations.{0}.xml", _currentName), String.Format("configurations.{0}.xml", selectedName));
                File.WriteAllText(file, xml);
            }

            foreach (var file in Directory.GetFiles(Environment.CurrentDirectory, "*services.xml", SearchOption.AllDirectories)) {
                var xml = File.ReadAllText(file);
                xml = xml.Replace(String.Format("services.{0}.xml", _currentName), String.Format("services.{0}.xml", selectedName));
                File.WriteAllText(file, xml);
            }

            _currentName = selectedName;

            Task.Factory.StartNew(() => Reset(shouldWipe))
                .ContinueWith(t => Dispatcher.Invoke(new Action(() => MessageBox.Show("Successfully switched backplane"))));
        }

        private void UpdateStatus(string message) {
            Dispatcher.Invoke(new Action(() => statusBarText.Text = message));
        }

        private void Reset(bool wipe) {
            var programFilesDir = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
            var pserviceBusDir = Directory.GetDirectories(programFilesDir)
                .FirstOrDefault(x => x.IndexOf("PServiceBus", StringComparison.OrdinalIgnoreCase) > 0);

            if (String.IsNullOrWhiteSpace(pserviceBusDir)) {
                UpdateStatus("Could not find any installation of PServiceBus on this machine. Press exit application");
                return;
            }


            var services = ServiceController.GetServices();

            var serviceMonitor = services.FirstOrDefault(x =>
                x.ServiceName.IndexOf("PServiceBus.ServiceMonitor", StringComparison.OrdinalIgnoreCase) >= 0);

            var redisService = services.FirstOrDefault(x =>
                x.ServiceName.IndexOf("PServiceBus.Redis Server", StringComparison.OrdinalIgnoreCase) >= 0);

            var psbServices = services.Where(x =>
                !(x.ServiceName.IndexOf("PServiceBus.ServiceMonitor", StringComparison.OrdinalIgnoreCase) >= 0 ||
                x.ServiceName.IndexOf("PServiceBus.Redis Server", StringComparison.OrdinalIgnoreCase) >= 0) &&
                x.ServiceName.StartsWith("PServiceBus.")
                ).ToList();

            UpdateStatus("Stopping PServiceBus.Monitor Service");
            if (serviceMonitor.Status != ServiceControllerStatus.Stopped)
                serviceMonitor.Stop();
            serviceMonitor.WaitForStatus(ServiceControllerStatus.Stopped);
            UpdateStatus("Stopping PServiceBus.Monitor Service Completed");

            UpdateStatus("Stopping all PServiceBus Services");
            psbServices.AsParallel().ForAll(x =>
            {
                if (x.Status != ServiceControllerStatus.Stopped)
                    x.Stop();
                x.WaitForStatus(ServiceControllerStatus.Stopped);
            });
            UpdateStatus("Stopping PServiceBus Services Completed");

            if (_currentName.Equals("redis", StringComparison.OrdinalIgnoreCase) && Directory.Exists(String.Format("{0}/Redis Server/",pserviceBusDir))) {

                UpdateStatus("Stopping PServiceBus.Redis Server");
                if (redisService.Status != ServiceControllerStatus.Stopped)
                    redisService.Stop();
                redisService.WaitForStatus(ServiceControllerStatus.Stopped);
                UpdateStatus("Stopping PServiceBus.Redis Server Completed");


                if (wipe) {
                    UpdateStatus("Clearing Redis database files");

                    var redisFiles = Directory.GetFiles(String.Format("{0}/Redis Server/",
                        pserviceBusDir), "*.rdb", SearchOption.TopDirectoryOnly).ToList();

                    redisFiles.ForEach(x =>
                    {
                        try { File.Delete(x); } catch { }
                    });

                    UpdateStatus("Clearing Redis database files Completed");
                }

                UpdateStatus("Starting PServiceBus.Redis Server");
                if (redisService.Status != ServiceControllerStatus.Running)
                    redisService.Start();
                redisService.WaitForStatus(ServiceControllerStatus.Running);
                UpdateStatus("Starting PServiceBus.Redis Server Completed");
            }

            UpdateStatus("Starting PServiceBus.Monitor Service");
            if (serviceMonitor.Status != ServiceControllerStatus.Running)
                serviceMonitor.Start();
            serviceMonitor.WaitForStatus(ServiceControllerStatus.Running);
            UpdateStatus("Starting PServiceBus.Monitor Service Completed");

            UpdateStatus("Waiting for all PServiceBus Services to Start");
            psbServices.AsParallel().ForAll(x =>
            {
                x.WaitForStatus(ServiceControllerStatus.Running);
            });

            UpdateStatus("PServiceBus Reset Successfully.");
        }

        private void Window_Loaded(object sender, RoutedEventArgs e) {

            var folder = new DirectoryInfo(Environment.CurrentDirectory);

            var files = folder.GetFiles("*", SearchOption.AllDirectories).Where(x => Regex.IsMatch(x.Name, "app.([^.]+).xml"));

            var defaultSettingFile = folder.GetFiles("*.config", SearchOption.AllDirectories).First(x => x.Directory.Name == "ESB").FullName;

            var settingXml = File.ReadAllText(defaultSettingFile);

            _currentName = Regex.Match(settingXml, "filename=\"(?<Name>[^\"]+)\"").Groups["Name"].Value.Split('.')[1];

            var keys = files.Select(x => x.Name).Distinct();

            foreach (var key in keys) {
                var tokens = key.Split('.');
                var name = tokens[1][0].ToString().ToUpper() + tokens[1].Substring(1);
                backplanes.Items.Add(new ComboBoxItem() { Content = name, Tag = key, IsSelected = name.Equals(_currentName, StringComparison.OrdinalIgnoreCase) });
            }
        }
    }
}
